#ifndef OWN_THUNK_THIS_TO_CDECL_H_080325
#define OWN_THUNK_THIS_TO_CDECL_H_080325

#include <Thunk/ThunkBase.h>

#define THIS_TO_CDECL_CODES()				\
/*	CALL Hook	*/							\
CONST	CODE_FIRST(byte,CALL,0xE8)			\
CONST	CODE(dword,HOOK,0)					\
											\
/*	this and member function	*/			\
		CODE(dword,m_method,0)				\
		CODE(dword_ptr,m_this,0)			\
											\
/*	member function return here!	*/		\
/*	MOV ESP,oldESP	*/						\
CONST	CODE(byte,MOV_ESP,0xBC)				\
CONST	CODE(dword,oldESP,0)				\
											\
/*	JMP oldRet	*/							\
CONST	CODE(byte,JMP,0xE9)					\
CONST	CODE(dword,oldRet,0)				\
											\
/*	RET	*/									\
//CONST	CODE(byte,RET,0xC3)

namespace Thunk
{
	class ThisToCdecl
	{
	public:

		~ThisToCdecl();
		explicit ThisToCdecl(const void *Obj=0,int method=0);
		ThisToCdecl(const ThisToCdecl &src);
		ThisToCdecl& operator = (const ThisToCdecl &rhs);

		bool operator == (const ThisToCdecl &rhs) const;
		bool operator != (const ThisToCdecl &rhs) const;

		const void* Attach(const void *newObj);
		int Attach(int newMethod);

		template<typename Method>
		int AttachMethod(Method newMethod);

		template<typename Callback>
		Callback MakeCallback() const;

		template<typename Callback>
		operator Callback() const { return MakeCallback<Callback>(); }

	private:

		static void Hook();

		dword_ptr GetObject() const;
		void SetObject(dword_ptr newObj);

		dword GetMethod() const;
		void SetMethod(dword newMethod);

#pragma pack( push , 1)
		THIS_TO_CDECL_CODES()
#pragma pack( pop )

	};

	template<typename Method>
	int ThisToCdecl::AttachMethod(Method newMethod)
	{
		return Attach( Helper::PointerToInt32(newMethod) );
	}

#pragma warning( push )
#pragma warning( disable : 4311 )
	template<typename Callback>
	Callback ThisToCdecl::MakeCallback() const
	{
		Helper::ReviseVirtualProtect((void*)this,sizeof(ThisToCdecl));
		return reinterpret_cast<Callback>( this );
	}
#pragma warning( pop )

}

#endif	//#ifndef OWN_THUNK_THIS_TO_CDECL_H_080325
